use async_graphql::{InputObject, SimpleObject, Union};
use linera_sdk::linera_base_types::{AccountOwner, Amount, ChainId};
use serde::{Deserialize, Serialize};

use rfq::{RequestId, TokenPair, Tokens};

use crate::state::{QuoteProvided, QuoteRequested};

#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject, InputObject)]
pub struct ExchangeInProgress {
    pub temp_chain_id: ChainId,
}

#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject, InputObject)]
pub struct AwaitingTokens {
    pub token_pair: TokenPair,
    pub amount_offered: Amount,
    pub quoter_account: AccountOwner,
    pub temp_chain_id: ChainId,
}

#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)]
pub struct TempChainTokenHolder {
    pub account_owner: AccountOwner,
    pub chain_id: ChainId,
}

#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)]
pub struct TempChainState {
    pub(crate) request_id: RequestId,
    pub(crate) initiator: ChainId,
    pub(crate) token_pair: TokenPair,
    pub(crate) tokens_in_hold: Option<Tokens>,
}

#[derive(Clone, Debug, Serialize, Deserialize, Union)]
pub enum RequestState {
    QuoteRequested(QuoteRequested),
    QuoteProvided(QuoteProvided),
    AwaitingTokens(Box<AwaitingTokens>),
    ExchangeInProgress(ExchangeInProgress),
}

impl RequestState {
    pub(crate) fn token_pair(&self) -> TokenPair {
        match self {
            RequestState::QuoteRequested(QuoteRequested { token_pair, .. })
            | RequestState::QuoteProvided(QuoteProvided { token_pair, .. }) => token_pair.clone(),
            _ => panic!("invalid state for reading the token pair"),
        }
    }
}
